﻿#pragma once
#include "AsNetworkMessage.h"

AS_MEMBER_CLASS_DECLARATION(AsNetworkTcpServer);

class AS_CORE_EXPORT AsNetworkTcpServer : public QObject, public AsBinder<AsNetworkTcpServer> {
	Q_OBJECT

public:
	explicit AsNetworkTcpServer(QObject* parent = nullptr);
	~AsNetworkTcpServer();

private:
	AS_MEMBER_CLASS(AsNetworkTcpServer)* mp;

public:
	bool startup(quint16 port, const QByteArray& authenticateKey = QByteArray());
	void stop();

	void setMaxPendingConnection(int maxPendingConnection);
	void setAuthenticateKey(const QByteArray& authenticateKey);
	void setSendingPeriod(int periodTime);

public:
	void sendMessage(const AsNetworkMessage& msg);
	bool sendMessage(QTcpSocket* client, const AsNetworkMessage& msg);
	bool sendMessage(const QString& client, const AsNetworkMessage& msg);
	
	bool takeMessage(QTcpSocket*& client, AsNetworkMessage& msg);
	bool takeMessage(QString& client, AsNetworkMessage& msg);
	AsNetworkMessage takeMessage();
	AsNetworkMessage takeMessage(QTcpSocket*& client);

	bool sendByteArray(const QByteArray& byteArray);
	bool sendByteArray(QTcpSocket* client, const QByteArray& byteArray);
	bool sendByteArray(QString& client, const QByteArray& byteArray);
	bool takeByteArray(QTcpSocket*& client, QByteArray& byteArray);
	bool takeByteArray(QString& client, QByteArray& byteArray);
	bool takeByteArray(QByteArray& byteArray);

public:
	template <typename _Slot>
	void bindConnected(_Slot slot) {
		if (isSignalConnected(metaObject()->method(metaObject()->indexOfSignal("sigConnected()"))))
			unbindSignal(SIGNAL(sigConnected()));
		bindSignal(&AsNetworkTcpServer::sigConnected, this, slot);
	}
	template <typename _Slot>
	void bindDisconnected(_Slot slot) {
		if (isSignalConnected(metaObject()->method(metaObject()->indexOfSignal("sigDisconnected()"))))
			unbindSignal(SIGNAL(sigDisconnected()));
		bindSignal(&AsNetworkTcpServer::sigDisconnected, this, slot);
	}
	template <typename _Slot>
	void bindReceived(_Slot slot) {
		if (isSignalConnected(metaObject()->method(metaObject()->indexOfSignal("sigReceived()"))))
			unbindSignal(SIGNAL(sigReceived()));
		bindSignal(&AsNetworkTcpServer::sigReceived, this, slot);
	}

signals:
	void sigConnected(QString clientHost);
	void sigDisconnected(QString clientHost);
	void sigReceived();

};
